package com.lzx.hbh_system.shiro;

import com.lzx.hbh_system.util.staitcParma.ResultEnum;
import org.apache.shiro.mgt.DefaultSessionStorageEvaluator;
import org.apache.shiro.mgt.DefaultSubjectDAO;
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.mgt.DefaultWebSessionStorageEvaluator;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;

import javax.servlet.Filter;
import java.util.LinkedHashMap;
import java.util.Map;
@Configuration
public class ShiroConfig {
    /**
     * 创建 ShiroFilterFactoryBean 过滤器bean工厂
     * filter 如果检测到请求头存在 token，则用 token 去 login，走 Realm 去验证
     */
    /**
     * 创建Realm
     * @Bean 将方法返回的对象放入Spring容器中，便于以上方法随时注入使用
     */
    @Bean
    public JWTRealm jwtRealm(){
        return new JWTRealm();
    }
    /**
     * 创建 DefaultWebSecurityManager 默认Web权限管理器
     */
    @Bean
    public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("jwtRealm") JWTRealm jwtRealm){
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        //把自己的jwtRealm 和 securityManager 关联起来
        securityManager.setRealm(jwtRealm);
        //关闭shiro的sessionid
        DefaultSubjectDAO defaultSubjectDAO = new DefaultSubjectDAO();
        DefaultSessionStorageEvaluator sessionStorageEvaluator = new DefaultSessionStorageEvaluator();
        sessionStorageEvaluator.setSessionStorageEnabled(false);
        defaultSubjectDAO.setSessionStorageEvaluator(sessionStorageEvaluator);
        securityManager.setSubjectDAO(defaultSubjectDAO);
        return securityManager;
    }
    @Bean
    public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("getDefaultWebSecurityManager") DefaultWebSecurityManager securityManager){
        ShiroFilterFactoryBean filterFactoryBean = new ShiroFilterFactoryBean();
        filterFactoryBean.setSecurityManager(securityManager);
        // 添加自定的登陆过滤器、和登出过滤器
//        Map<String, Filter> filterMap = filterFactoryBean.getFilters();
        Map<String, Filter> filterMap = new LinkedHashMap<>();//https://blog.csdn.net/weixin_44852935/article/details/107683290?utm_medium=distribute.pc_relevant.none-task-blog-2~default~baidujs_baidulandingword~default-0.pc_relevant_default&spm=1001.2101.3001.4242.1&utm_relevant_index=3
        // 命名改过滤器 ”jwt“
        filterMap.put("jwt",new JWTFilter());
//        filterMap.put("logout",new UserLogoutFilter()); 不使用原因详情：CTRL+2
        //设置无权限跳转的路径URL
        filterFactoryBean.setUnauthorizedUrl("/error/"+ ResultEnum.USER_NOTMATCH_ROLE_OR_PEMISSION.getCode()+"/"+ResultEnum.USER_NOTMATCH_ROLE_OR_PEMISSION.getMsg());
        //设置我们自定义的过滤器
        filterFactoryBean.setFilters(filterMap);
        /*
         * 自定义URL规则
         */
        Map<String,String> filterRuleMap = new LinkedHashMap<>();
        //访问”anon“标识的路径，不通过我们的filter
        //-不过滤
        filterRuleMap.put("/user/checklogin","anon");//登陆
        filterRuleMap.put("/user/logout","anon");//用户退出，具体实现在客户端，客户端清除登陆的token。
        filterRuleMap.put("/user/registerUser","anon");//注册
        filterRuleMap.put("/user/getInfo","anon");//游客访问主页，获取可以游客浏览的信息
        filterRuleMap.put("/sse/**","anon");//sse服务接口。
        filterRuleMap.put("/error/**","anon");//异常处理响应不通过Filter。
        //-过滤其余所有请求
        filterRuleMap.put("/**","jwt");//所有请求路径通过自定 jwt的过滤器
        filterFactoryBean.setFilterChainDefinitionMap(filterRuleMap);
        return filterFactoryBean;
    }


    /**
     * 下面的代码是添加注解支持
     */
    @Bean
    @DependsOn("lifecycleBeanPostProcessor")
    public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
        DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
        // 强制使用cglib，防止重复代理和可能引起代理出错的问题
        // https://zhuanlan.zhihu.com/p/29161098
        defaultAdvisorAutoProxyCreator.setProxyTargetClass(true);
        return defaultAdvisorAutoProxyCreator;
    }

    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(@Qualifier("getDefaultWebSecurityManager")DefaultWebSecurityManager securityManager) {
        AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor();
        advisor.setSecurityManager(securityManager);
        return advisor;
    }
    @Bean
    public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
        return new LifecycleBeanPostProcessor();
    }

}
